package com.its.common.net.core;

import cn.hutool.extra.spring.SpringUtil;
import com.its.common.net.core.config.NetHandlerThreadPoolConfig;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;

/**
 * @Author xiaxp
 * @Date 8/24/22 17:45
 * @Description
 */
@Slf4j
public abstract class BaseNetHandlerExecutor<T> implements INetHandlerExecutor<T> {
    private static final String HANDLER_EXECUTOR_POOL_NAME = "ITS-Net-Handler-Executor-Pool";
    private Executor executor;
    protected NetHandlerThreadPoolConfig config;

    public BaseNetHandlerExecutor(){
        initHandlerExecutor();
    }

    private void initHandlerExecutor(){
        if(null != this.executor){
            return;
        }

        NetHandlerThreadPoolConfig config = SpringUtil.getBean(NetHandlerThreadPoolConfig.class);
        if(null == config){
            this.config = new NetHandlerThreadPoolConfig();
        }else{
            this.config = config;
        }

        this.executor = new ThreadPoolExecutor(
                this.config.getCoolPoolSize(),
                this.config.getMaxPoolSize(),
                this.config.getIdleTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(this.config.getQueueCap()),
                new DefaultThreadFactory(HANDLER_EXECUTOR_POOL_NAME, true));
    }

    @Override
    public T execute(Object... reqs) {
        return doExec(reqs);
    }

    @Override
    public Future<T> asyncExecute(Promise<T> promise, Object... reqs) {
        if (promise == null) {
            throw new IllegalArgumentException("promise should not be null");
        }
        executor.execute(() -> {
            try {
                T rep = doExec(reqs);
                promise.setSuccess(rep);
            } catch (Exception e) {
                promise.setFailure(e);
            }
        });
        return promise;
    }


    /** 实际子类执行
     * @param reqs 请求
     * @return 响应
     */
    protected abstract T doExec(Object... reqs);
}
